# -*- coding:utf8 -*-
import json
import traceback
import os
import re
import typing
from scrapy import Request, FormRequest
from squirrel_core.commons.utils.tools import calc_str_md5, upload_file
from squirrel_core.frame.spider_makaka import MakakaSpider

file_path = os.environ.get("FILE_PATH", "/")


class luojiweiye_score(MakakaSpider):
    name = "luojiweiye_score"
    serialNumber = ""
    card_num = ""
    header = {
        "Host": "sport.luojiweiye.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
        "Accept": "application/json, text/plain, */*"
    }
    continue_flag = True

    def get_ext_requests_or_urls(self, data=None):
        if data and isinstance(data, str):
            data = json.loads(data)
        if data and isinstance(data, typing.MutableMapping):
            self.serialNumber = data.get("serialNumber", "")
            race_id = data.get("spider_config", {}).get("race_id", "")
            user_id = data.get("spider_config", {}).get("user_id", "")
            race_no = data.get("spider_config", {}).get("race_no", "")
            self.card_num = data.get("spider_config", {}).get("card_num", "")
            user_name = data.get("spider_config", {}).get("user_name", "")
            card_num = data.get("spider_config", {}).get("card_num", "")
            race_name = data.get("spider_config", {}).get("race_name", "").replace(" ", "")
            home_url = data.get("spider_config", {}).get("url", "")
            if not user_name and not race_no:
                self.logger.info("user_name和race_no必须存在一个")
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 101, "message": "user_name和race_no必须存在一个"})
                self.close_after_idle = True
                self.force_to_close_spider = True
            else:
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 100, "message": "任务启动成功"})
                activity_id = "".join(re.findall(r"id=(\d+)", home_url)).strip()
                if "my-grade" in home_url:
                    for param in [{"id_num": card_num}, {"name": user_name}]:
                        url = f'https://sport.luojiweiye.com/api/grade/new_my_list?game_id={activity_id}&name=&params={json.dumps(param)}&page_size=5&page=1&api_token=&platform=&lang='
                        yield Request(url=url, callback=self.parse_id, dont_filter=True, errback=self.err_parse, headers=self.header,
                                      meta={"race_id": race_id, "race_no": race_no, "user_id": user_id, "user_name": user_name,
                                            "race_name": race_name, "activity_id": activity_id})
                else:
                    keyword = race_no or user_name
                    url = f"https://sport.luojiweiye.com/api/sport/packages/for-result?activity_id={activity_id}"
                    yield Request(url=url, callback=self.parse, dont_filter=True, errback=self.err_parse, headers=self.header,
                                  meta={"race_id": race_id, "race_no": race_no, "user_id": user_id, "user_name": user_name,
                                        "race_name": race_name, "activity_id": activity_id, "keyword": keyword})

    def parse(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_name = response.meta.get("race_name", "")
        activity_id = response.meta.get("activity_id", "")
        keyword = response.meta.get("keyword", "")
        race_no = response.meta.get("race_no", "")
        user_name = response.meta.get("user_name", "")
        try:
            self.logger.info(f"开始解析赛事组别信息:{response.url}")
            data_list = json.loads(response.text).get("data", [])
            for data in data_list:
                group_name = data.get("name", "")
                group_value = data.get("value", "")
                url = f"https://sport.luojiweiye.com/api/web/players?activity_id={activity_id}&package_id={group_value}&page=1&page_size=20&sex=&real_name={keyword}&age_range=&user_id="
                yield Request(url=url, callback=self.parse_user, dont_filter=True,
                              errback=self.err_parse, headers=self.header,
                              meta={"race_id": race_id, "group_name": group_name, "user_id": user_id, "race_no": race_no,
                                    "race_name": race_name, "keyword": keyword, "activity_id": activity_id, "user_name": user_name})
        except Exception:
            self.logger.info(f"解析赛事组别信息时出错{response.url}：{traceback.format_exc()}")

    def parse_user(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_name = response.meta.get("race_name", "")
        group_name = response.meta.get("group_name", "")
        keyword = response.meta.get("keyword", "")
        activity_id = response.meta.get("activity_id", "")
        race_no = response.meta.get("race_no", "")
        user_name = response.meta.get("user_name", "")
        try:
            self.logger.info(f"开始查找{group_name}的player_id信息:{response.url}")
            data_list = json.loads(response.text).get("data", {}).get("data", [])
            for data in data_list:
                if data.get("no", "") == race_no and data.get("name", "") == user_name:
                    score_id = data.get("id")
                    _distance = data.get("cp_mileage", "")
                    url = f"https://sport.luojiweiye.com/api/sport/admin/result?player_id={score_id}"
                    yield Request(url=url, callback=self.parse_score, dont_filter=True,
                                  errback=self.err_parse, headers=self.header,
                                  meta={"race_id": race_id, "group_name": group_name, "user_id": user_id,
                                        "race_name": race_name, "keyword": keyword, "_distance": _distance, "activity_id": activity_id})
        except Exception:
            self.logger.info(f"查找{group_name}的player_id信息时出错{response.url}：{traceback.format_exc()}")

    def parse_id(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_name = response.meta.get("race_name", "")
        activity_id = response.meta.get("activity_id", "")
        race_no = response.meta.get("race_no", "")
        user_name = response.meta.get("user_name", "")
        try:
            self.logger.info(f"开始解析赛事组别信息:{response.url}")
            data_list = json.loads(response.text).get("data", [])
            for data in data_list:
                if data.get("no", "") == race_no and data.get("name", "") == user_name:
                    score_id = data.get("id", "")
                    group_name = data.get("package_name", "")
                    url = f"https://sport.luojiweiye.com/api/sport/admin/result?player_id={score_id}"
                    yield Request(url=url, callback=self.parse_score, dont_filter=True,
                                  errback=self.err_parse, headers=self.header,
                                  meta={"race_id": race_id, "user_id": user_id, "group_name": group_name,
                                        "race_name": race_name, "keyword": user_name,
                                        "activity_id": activity_id})
        except Exception:
            self.logger.info(f"解析赛事组别信息时出错{response.url}：{traceback.format_exc()}")

    def parse_score(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_name = response.meta.get("race_name", "")
        group_name = response.meta.get("group_name", "")
        keyword = response.meta.get("keyword", "")
        activity_id = response.meta.get("activity_id", "")
        _distance = response.meta.get("_distance", "")
        try:
            self.logger.info(f"开始解析{keyword}的成绩:{response.url}")
            content = json.loads(response.text).get("data", {})
            player_info = content.get("player", {})
            distance = "".join(re.findall(r"(\d+)KM", group_name)) or _distance
            race_no = player_info.get("no", "")
            user_name = player_info.get("name", "")
            shot_score = player_info.get("result_qiang", "")
            score = player_info.get("result_jing", "")
            if self.continue_flag:
                self.continue_flag = False
                ranks = {
                            "allRanks": {
                                "scoreRank": player_info.get("all_order", ""),
                                "shotScoreRank": player_info.get("all_order_qiang", "")
                            },
                            "sexRanks": {
                                "scoreRank": player_info.get("order_jing", ""),
                                "shotScoreRank": player_info.get("order_qiang", ""),
                            },
                            "ageRanks": {
                                "scoreRank": player_info.get("age_order", ""),
                                "shotScoreRank": player_info.get("age_order", ""),
                            }
                }
                score_data = {"race_name": player_info.get("activity_name", "") or race_name, "itemName": group_name, "name": user_name, "raceNo": race_no,
                              "distance": f"{distance}KM", "shotScore": shot_score, "score": score, "ranks": ranks}
                score_info = []
                data_list = content.get("results", [])
                for data in data_list:
                    cp_name = data.get("cp_name", "")
                    start_time = data.get("when", "")
                    stop_time = data.get("time_used", "")
                    cp_length = data.get("cp_mileage", "")
                    speed = data.get("speed_allocation", "")
                    score_info.append(
                        {"cp_name": cp_name, "start_time": start_time, "score": stop_time, "distance": cp_length,
                         "pace": speed})
                if score_info:
                    score_info[-1]["cp_name"] = "FINISH"
                score_data["sectionScore"] = score_info
                score_data.update({"fastPace": "", "slowPace": "", "pace": player_info.get("avg_peisu2", ""), "certImg": ""})
                cert_url = player_info.get("cert", "")
                if cert_url:
                    yield Request(url=cert_url, callback=self.parse_pic,  errback=self.err_parse,
                                  meta={"race_id": race_id, "user_id": user_id, "keyword": keyword, "score_data": score_data})
                else:
                    post_data = {"game_id": activity_id, "history": "0", "params": json.dumps({"id_num": self.card_num})}
                    url = "https://sport.luojiweiye.com/api/cert/down"
                    yield FormRequest(url=url, callback=self.parse_cert, dont_filter=True,
                                      errback=self.err_parse, headers={"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"},
                                      formdata=post_data, meta={"race_id": race_id, "user_id": user_id, "user_name": user_name, "group_name": group_name,
                                                                "keyword": keyword, "score_data": score_data})
        except Exception:
            self.logger.info(f"查找{keyword}的成绩时出错{response.url}：{traceback.format_exc()}")

    def parse_cert(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        keyword = response.meta.get("keyword", "")
        user_name = response.meta.get("user_name", "")
        group_name = response.meta.get("group_name", "")
        score_data = response.meta.get("score_data", {})
        try:
            self.logger.info(f"开始解析{keyword}的证书链接：{response.url}")
            cert_url = ""
            data_list = json.loads(response.text).get("data", [])
            for data in data_list:
                if data.get("name", "") == user_name and data.get("package_name", "") == group_name:
                    cert_url = data.get("cert", "")
                    break
            if cert_url:
                yield Request(url=cert_url, callback=self.parse_pic,  errback=self.err_parse,
                              meta={"race_id": race_id, "user_id": user_id, "keyword": keyword, "score_data": score_data})
            else:
                result = self.result_item_assembler(response)
                result['result_data'] = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                         "crawlerType": self.name_second, "data": str(score_data)}
                yield result
        except Exception:
            self.logger.info(f"解析{keyword}证书链接时出错{response.url}：{traceback.format_exc()}")

    def parse_pic(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        keyword = response.meta.get("keyword", "")
        score_data = response.meta.get("score_data", {})
        try:
            self.logger.info(f"开始下载{keyword}的证书：{response.url}")
            pic_md5 = calc_str_md5(response.url)
            pic_name = f"{keyword}_{pic_md5}.jpg"
            dir_path = os.path.join(file_path, "picture", self.name_first)
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
            save_path = os.path.join(dir_path, pic_name)
            if not os.path.exists(save_path):
                with open(save_path, "wb") as f:
                    f.write(response.body)
                upload_path = f"flow/{race_id}/{user_id}/pic/{pic_name}"
                upload_flag = upload_file(save_path, upload_path)
                if upload_flag:
                    self.logger.info(f"{save_path}上传成功：{upload_path}")
                else:
                    self.logger.info(f"{save_path}上传失败：{upload_path}")
                score_data["certImg"] = upload_path
                result = self.result_item_assembler(response)
                result['result_data'] = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                         "crawlerType": self.name_second, "data": str(score_data)}
                yield result
        except Exception:
            self.logger.info(f"下载{keyword}证书时出错{response.url}：{traceback.format_exc()}")

    def err_parse(self, failure):
        self.logger.warning(f"请求失败：{failure.request.url},错误原因:{traceback.format_exc()}")

